package com.xiaoshuidi.cloud.module.contract.api.bill;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.contract.api.ContractRentOrderApi;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.OrderFeesDetaillVo;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.orderFees.OrderFeesVo;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.rentOrder.RentOrderCreateReq;
import com.xiaoshuidi.cloud.module.contract.convert.contract.CustomerCompanyConvert;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.CustomerCompanyDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.SettlementDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.SettlementDetailDO;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.OrderFeesMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.RentOrderMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.contract.SettlementDetailMapper;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.contract.SettlementMapper;
import com.xiaoshuidi.cloud.module.contract.enums.bill.OrderPayStatusEnum;
import com.xiaoshuidi.cloud.module.contract.enums.bill.OrderTypeEnum;
import com.xiaoshuidi.cloud.module.contract.enums.contract.EvictionTypeEnum;
import com.xiaoshuidi.cloud.module.contract.enums.settlement.SettlementStatusEnum;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractSettlementService;
import com.xiaoshuidi.cloud.module.contract.vo.*;
import com.xiaoshuidi.cloud.module.contract.convert.bill.RentOrderConvert;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.OrderFeesDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.RentOrderDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.ContractRoomDO;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.contract.ContractRoomMapper;
import com.xiaoshuidi.cloud.module.contract.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.contract.enums.contract.ContractStatusEnum;
import com.xiaoshuidi.cloud.module.contract.service.bill.OrderFeesService;
import com.xiaoshuidi.cloud.module.contract.service.bill.RentOrderService;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractInvoiceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
@Slf4j
public class ContractRentOrderApiImpl implements ContractRentOrderApi {

    @Resource
    private RentOrderService rentOrderService;
    @Resource
    private OrderFeesService orderFeesService;
    @Resource
    private OrderFeesMapper orderfeesMapper;
    @Resource
    private ContractInvoiceService companyInvoiceService;
    @Resource
    private RentOrderMapper rentOrderMapper;
    @Resource
    private ContractRoomMapper contractRoomMapper;
    @Resource
    private SettlementMapper settlementMapper;
    @Resource
    private SettlementDetailMapper settlementDetailMapper;


    @Override
    public CommonResult<PageResult<OrderInvoicePageRespVO>> getInvoiceList(OrderInvoicePageReqVO reqVO) {
        Page<OrderInvoicePageRespVO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());
        rentOrderMapper.getInvoiceList(page, reqVO);
        List<OrderInvoicePageRespVO> data = page.getRecords();
        for (OrderInvoicePageRespVO respVO : data) {
            respVO.setIsInvoice(StringUtils.equals(respVO.getInvoiceStatus(), "2") ? "Y" : "N");
        }
        if(CollectionUtil.isNotEmpty(data)){
            CommonResult<List<RentOrderExtVO>> actualExpensesByOrderIds =
                    getActualExpensesByOrderIds(data.stream().map(OrderInvoicePageRespVO::getOrderId).collect(Collectors.toList()));
            List<RentOrderExtVO> dataList = actualExpensesByOrderIds.getData();
            data.forEach(d->{
                dataList.stream().filter(f->f.getId().compareTo(d.getOrderId())==0).findFirst()
                        .ifPresent(p->{
                            d.setInvoiceAmount(p.getPaidRentUtilities());
                        });
            });
        }
        PageResult<OrderInvoicePageRespVO> result = new PageResult<>();
        result.setList(data);
        result.setTotal(page.getTotal());
        return CommonResult.success(result);
    }

    @Override
    public CommonResult<List<ContractInvoiceDetailVO>> getOrderDetailList(Long invoiceId) {
//        List<ContractInvoiceDetailVO> orderDetailList = rentOrderMapper.getOrderDetailList(invoiceId);
        List<ContractInvoiceDetailVO> orderDetailList = new ArrayList<>();
        CommonResult<List<RentOrderExtVO>> actualExpensesByOrderIds =
                getActualExpensesByOrderIds(Arrays.asList(invoiceId));
        List<RentOrderExtVO> dataList = actualExpensesByOrderIds.getData();
        if(CollectionUtil.isNotEmpty(dataList)){
            Optional.ofNullable(dataList.get(0).getFeeDetail()).ifPresent(p->{
                p.forEach(f->{
                    ContractInvoiceDetailVO vo = new ContractInvoiceDetailVO();
                    vo.setOrderId(f.getOrderId().toString());
                    vo.setAmount(f.getAmount().toString());
                    vo.setInvoiceAmount(f.getAmount().toString());
                    vo.setFeeName(f.getFeeName());
                    vo.setStartTime(ObjectUtil.isNotEmpty(f.getStartTime())? f.getStartTime().toString():"");
                    vo.setEndTime(ObjectUtil.isNotEmpty(f.getEndTime())? f.getEndTime().toString():"");
                    orderDetailList.add(vo);
                });
            });
        }
        return CommonResult.success(orderDetailList);
    }

    @Override
    public CommonResult<List<ContractInvoiceDetailVO>> getOrderDetailListByOrderNo(Long invoiceId) {
        return CommonResult.success(rentOrderMapper.getOrderDetailListByOrderNo(invoiceId));
    }

    @Override
    public CommonResult<RentOrderExtVO> getById(@RequestParam("id") Long id) {
        RentOrderDO rentOrderDO = rentOrderService.getContractRentOrder(id);
        RentOrderExtVO rentOrderExtVO = RentOrderConvert.INSTANCE.convert2(rentOrderDO);
        if (rentOrderDO != null) {
            List<OrderFeesDO> feeDetails = orderFeesService.getOrderFeesByOrderId(id);
            rentOrderExtVO.setFeeDetail(RentOrderConvert.INSTANCE.convert2(feeDetails));
        } else {
            return CommonResult.error(ErrorCodeConstants.ROOM_ORDER_NOT_EXISTS);
        }
        return CommonResult.success(rentOrderExtVO);
    }

    @Override
    public CommonResult<Boolean> updateOrderInvoiceStatus(Long id) {
        rentOrderService.updateById(RentOrderDO.builder().id(id).invoiceStatus(11).build());
        List<OrderFeesDetaillVo> detailVos = orderFeesService.getOrderDetail(id);
        detailVos.forEach(orderFeesDetail -> {
            orderfeesMapper.updateById(OrderFeesDO.builder().id(orderFeesDetail.getId()).invoiceStatus(11).build());
        });
        return CommonResult.success();
    }

    @Override
    public CommonResult<String> checkOrderTime(Long invoiceId) {
        LambdaQueryWrapper<RentOrderDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RentOrderDO::getInvoiceId, invoiceId);
        List<RentOrderDO> orders = rentOrderMapper.selectList(wrapper);
        for (RentOrderDO order : orders) {
            LocalDateTime nowTime = LocalDateTime.now();
            LocalDateTime actualPayTime = order.getActualPayTime();
            LocalDate localDate1 = nowTime.toLocalDate();
            LocalDate localDate2 = actualPayTime.toLocalDate();
            Period period = Period.between(localDate1, localDate2);
            int timeNum = actualPayTime.compareTo(nowTime);
            if (period.getYears() > 1 || (period.getYears() == 1 && (period.getMonths() > 0 || period.getDays() > 0))) {
                return CommonResult.success("fail");
            }
        }
        return CommonResult.success("success");
    }

    @Override
    public CommonResult<Boolean> updateOrderByInvalidateInvoice(Long invoiceId) {
        LambdaQueryWrapper<RentOrderDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RentOrderDO::getInvoiceId, invoiceId);
        List<RentOrderDO> orders = rentOrderMapper.selectList(wrapper);
        orders.forEach(order -> {
            rentOrderService.updateById(RentOrderDO.builder().id(order.getId()).invoiceStatus(0).build());
            List<OrderFeesDetaillVo> detailVos = orderFeesService.getOrderDetail(order.getId());
            detailVos.forEach(orderFeesDetail -> {
                orderfeesMapper.updateById(OrderFeesDO.builder().id(orderFeesDetail.getId()).invoiceStatus(0).build());
            });
        });
        return CommonResult.success();
    }

    @Override
    public CommonResult<Boolean> updateOrderByRushRed(Long invoiceId, int invoiceStatus) {
        LambdaQueryWrapper<RentOrderDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RentOrderDO::getInvoiceId, invoiceId);
        List<RentOrderDO> orders = rentOrderMapper.selectList(wrapper);
        orders.forEach(order -> {
            rentOrderService.updateById(RentOrderDO.builder().id(order.getId()).invoiceStatus(invoiceStatus).build());
            List<OrderFeesDetaillVo> detailVos = orderFeesService.getOrderDetail(order.getId());
            detailVos.forEach(orderFeesDetail -> {
                orderfeesMapper.updateById(OrderFeesDO.builder().id(orderFeesDetail.getId()).invoiceStatus(invoiceStatus).build());
            });
        });
        return CommonResult.success();
    }

    @Override
    public CommonResult<Boolean> orderInvoiceStatus(List<Long> orderIdList, Long invoiceId, int invoiceStatus) {
        orderIdList.forEach(orderId -> {
            rentOrderService.updateById(RentOrderDO.builder().id(orderId).invoiceId(invoiceId).invoiceStatus(invoiceStatus).build());
            List<OrderFeesDetaillVo> detailVos = orderFeesService.getOrderDetail(orderId);
            detailVos.forEach(orderFeesDetail -> {
                orderfeesMapper.updateById(OrderFeesDO.builder().id(orderFeesDetail.getId()).invoiceStatus(invoiceStatus).build());
            });
        });
        return CommonResult.success();
    }

    @Override
    public CommonResult<Boolean> updateOrderStatus(Long id, String status, String oldStatus) {
        rentOrderService.updateById(RentOrderDO.builder().id(id).payStatus(status).oldPayStatus(oldStatus).build());
        return CommonResult.success();
    }

    /**
     * 批量修改企业账单状态为处理中
     *
     * @param batchId 批量付款号
     * @param status
     * @status status
     */
    @Override
    public CommonResult<Boolean> updateOrderBatchStatus(String batchId, String status) {
        //查询批支付下账单
        List<RentOrderDO> rentListByBatchNo = rentOrderService.getRentListByBatchNo(batchId);
        if (CollectionUtil.isNotEmpty(rentListByBatchNo)) {
            List<RentOrderDO> collect =
                    rentListByBatchNo.stream().filter(f -> OrderPayStatusEnum.PART.getCode().equals(f.getPayStatus())
                                    || OrderPayStatusEnum.UNPAID.getCode().equals(f.getPayStatus()))
                            .map(m -> RentOrderDO.builder().id(m.getId()).payStatus(status).oldPayStatus(m.getPayStatus()).build())
                            .collect(Collectors.toList());
            rentOrderService.updateBatch(collect);

        }
        return CommonResult.success();
    }

    /**
     * 批量还原修改企业账单状态
     *
     * @param batchId 批量付款号
     * @return
     * @status status
     */
    @Override
    public CommonResult<Boolean> rollbackOrderBatchStatus(String batchId) {
        //查询批支付下账单
        List<RentOrderDO> rentListByBatchNo = rentOrderService.getRentListByBatchNo(batchId);
        if (CollectionUtil.isNotEmpty(rentListByBatchNo)) {
            List<RentOrderDO> collect =
                    rentListByBatchNo.stream().filter(f -> StrUtil.isNotBlank(f.getOldPayStatus())
                                    && OrderPayStatusEnum.PROCESS.getCode().equals(f.getPayStatus()))
                            .map(m -> RentOrderDO.builder().id(m.getId()).payStatus(m.getOldPayStatus()).build())
                            .collect(Collectors.toList());
            rentOrderService.updateBatch(collect);

        }
        return CommonResult.success();
    }


    /**
     * 获取选择开票的企业账单明细信息
     *
     * @param reqVO
     * @return
     */
    @Override
    public CommonResult<List<CompanyInvoiceRespVO>> getCompanyInvoiceableOrder(CompanyInvoiceReqVO reqVO) {
        return CommonResult.success(companyInvoiceService.getCompanyInvoiceable(reqVO));
    }

    @Override
    public CommonResult<Void> setInvoiceRecordId(Long invoiceRecordId, List<Long> feeDetailId) {
        companyInvoiceService.setInvoiceRecordId(invoiceRecordId, feeDetailId);
        return CommonResult.success();
    }

    @Override
    public CommonResult<Long> createOrder(RentOrderCreateMeterReq req) {
        /**
         * 查询 已入住的 合同
         * */
        LambdaQueryWrapper<ContractRoomDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ContractRoomDO::getRoomId, req.getRoomId())
                .eq(ContractRoomDO::getContractStatus, ContractStatusEnum.CHECK_IN.getCode())
        ;
        ContractRoomDO contractRoomDO = contractRoomMapper.selectOne(lambdaQueryWrapper);
        if (contractRoomDO == null) {
            return CommonResult.success();
        }
        req.setContractId(contractRoomDO.getId());
        req.setApartmentId(contractRoomDO.getApartmentId());
        req.setApartmentName(contractRoomDO.getApartmentName());
        req.setRoomId(contractRoomDO.getRoomId());
        req.setRoomName(contractRoomDO.getRoomName());
        RentOrderCreateReq orderFeesCreateVO = RentOrderConvert.INSTANCE.convertMeter(req);
        List<OrderFeesVo> orderFeesVo = orderFeesCreateVO.getOrderFeesVo();
        log.info("=========费项类型的转换值：{}", orderFeesVo);
        List<OrderFeesVo> orderFeesVos = RentOrderConvert.INSTANCE.convertFeesList(req.getOrderFeesVo());
        orderFeesCreateVO.setOrderFeesVo(orderFeesVos);
        log.info("=========费项类型的copy后的值：{}", orderFeesVos);
        List<RentOrderDO> rentOrder = rentOrderService.createRentOrder(orderFeesCreateVO, Boolean.FALSE);
        log.info("======账单数据rentOrder：rentOrder");
        if (CollectionUtils.isNotEmpty(rentOrder)) {
            RentOrderDO rentOrderDO = rentOrder.stream().findFirst().get();
            return CommonResult.success(rentOrderDO.getId());
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult<List<RentOrderSowTicketVO>> getSowTicketOrder(Long sowTicketId) {
        return CommonResult.success(rentOrderService.getOrderBySowTicket(sowTicketId));
    }

    /**
     * 根据工单id列表获取对应的维修工单账单信息
     * @param getSowTicketOrderByIdsReq
     * @return
     */
    @Override
    public CommonResult<Map<Long, List<RentOrderSowTicketVO>>> getSowTicketOrderByIds(GetSowTicketOrderByIdsReq getSowTicketOrderByIdsReq) {
        return CommonResult.success(rentOrderService.getSowTicketOrderByIds(getSowTicketOrderByIdsReq));
    }

    @Override
    public CommonResult<OrderFeeAmountRespVO> getOrderAmountByFee(OrderFeeAmountReqVO req) {
        return CommonResult.success(orderFeesService.getOrderAmountByFee(req));
    }

    @Override
    @TenantIgnore
    public CommonResult<List<RentOrderExtVO>> getPaymentRentOrderList(String startTime, String endTime) {
        LambdaQueryWrapper<RentOrderDO> qw = new LambdaQueryWrapper<>();
        qw.eq(RentOrderDO::getPayStatus,"payment");
        qw.between(RentOrderDO::getActualPayTime,startTime,endTime);
        List<RentOrderDO> rentOrderDOList = rentOrderMapper.selectList(qw);
        List<RentOrderExtVO> rentOrderExtVOList = Optional.ofNullable(rentOrderDOList).orElse(new ArrayList<>()).stream().map(entity ->{
            RentOrderExtVO orderExtVO = RentOrderConvert.INSTANCE.convert2(entity);
            List<OrderFeesDO> feeDetails = orderFeesService.getOrderFeesByOrderId(orderExtVO.getId());
            orderExtVO.setFeeDetail(RentOrderConvert.INSTANCE.convert2(feeDetails));
            return orderExtVO;
        }).collect(Collectors.toList());
        return CommonResult.success(rentOrderExtVOList);
    }

    /**
     * 账单集合获取账单实际支付信息
     *
     * @param ids
     * @return
     */
    @Override
    public CommonResult<List<RentOrderExtVO>> getActualExpensesByOrderIds(List<Long> ids) {
        List<RentOrderExtVO> collect = new ArrayList<>();
        LambdaQueryWrapper<RentOrderDO> eq = new LambdaQueryWrapper<RentOrderDO>()
                .eq(RentOrderDO::getPayStatus, OrderPayStatusEnum.PAID.getCode())
                .in(RentOrderDO::getId,ids)
                .eq(RentOrderDO::getRestrictedInvoice,0);
        List<RentOrderDO> rentOrderDOList = rentOrderMapper.selectList(eq);
        if(CollectionUtil.isEmpty(rentOrderDOList)){
//            throw new ServiceException(ErrorCodeConstants.CONTRACT_NOT_EXISTS.getCode(), "未找到账单！！！");
            return CommonResult.success(collect);
        }

        //合同ids
        Set<Long> contractIds = rentOrderDOList.stream().map(RentOrderDO::getBusinessId).collect(Collectors.toSet());
        //获取合同信息
        List<ContractRoomDO> contractRoomDOList = contractRoomMapper.selectBatchIds(contractIds);
/*        if(CollectionUtil.isEmpty(contractRoomDOList) && contractRoomDOList.size()!=contractIds.size()){
            throw new ServiceException(ErrorCodeConstants.CONTRACT_NOT_EXISTS.getCode(), "未找到账单关联合同细信息！！！");
        }*/
        if(CollectionUtil.isEmpty(contractRoomDOList)){
            return CommonResult.success(collect);
        }
        //账单费项查询
        List<OrderFeesDO> orderFeesDOS = orderfeesMapper.selectList(new LambdaQueryWrapper<OrderFeesDO>()
                .in(OrderFeesDO::getOrderId,ids));


        //批量获取清算单
        LambdaQueryWrapper<SettlementDO> settlementDOLambdaQueryWrapper = new LambdaQueryWrapper<SettlementDO>().in(SettlementDO::getClearedStatus
                        , Arrays.asList(SettlementStatusEnum.CLEAR.getCode(),
                                        SettlementStatusEnum.HAVE_TAKEN_EFFECT.getCode(),
                                        SettlementStatusEnum.NO_AUDIT_REQUITED.getCode()))
                .in(SettlementDO::getContractId, contractIds);
        List<SettlementDO> settlementDOList = settlementMapper.selectList(settlementDOLambdaQueryWrapper);
        List<SettlementDetailDO> settlementDetailDOS = new ArrayList<>();
        //清算单明细
        if(CollectionUtil.isNotEmpty(settlementDOList)){
            Set<Long> smIds = settlementDOList.stream().map(SettlementDO::getId).collect(Collectors.toSet());
             settlementDetailDOS = settlementDetailMapper.selectList(SettlementDetailDO::getSettlementId,
                    smIds);
        }


        List<SettlementDetailDO> finalSettlementDetailDOS = settlementDetailDOS;
        collect = Optional.ofNullable(rentOrderDOList).orElse(new ArrayList<>()).stream()
                .map(m -> {
            RentOrderExtVO orderExtVO = null;
            //查找合同
                    Optional<ContractRoomDO> first =
                            contractRoomDOList.stream().filter(fr -> fr.getId().compareTo(m.getBusinessId()) == 0).findFirst();
                    //合同进行处理
                    if(first.isPresent()){
                        orderExtVO = RentOrderConvert.INSTANCE.convert2(m);
                        ContractRoomDO contractRoomDO = first.get();
                        //获取账单下明细
                        List<OrderFeesDO> feeDetails = orderFeesDOS.stream().filter(f->f.getOrderId().compareTo(m.getId())==0).collect(Collectors.toList());

                        //冻结不允许开票
                        if(ContractStatusEnum.FREEZE.getCode().equals(contractRoomDO.getContractStatus())){
                            log.info("冻结不允许开票{}",contractRoomDO.getRoomName());
                            return null;
                        }

                        //获取非押金数据并且有金额数据
                        List<OrderFeesDO> orderFeesDOListNodeposit = feeDetails.stream().filter(fds -> !fds.getFeeName().contains("押金") &&
                                fds.getAmount().compareTo(BigDecimal.ZERO)>0)
                                .peek(p->{
                                    //租金的费项目
                                    if(p.getFeeId()==1){
                                        p.setAmount(p.getAmount().subtract(ObjectUtil.isNotEmpty(m.getCouponDiscount())?m.getCouponDiscount():BigDecimal.ZERO));
                                    }
                                }).collect(Collectors.toList());

                        //无其他费项不进行处理
                        if(CollectionUtil.isEmpty(orderFeesDOListNodeposit)){
                            log.info("无其他费项不进行处理{}",contractRoomDO.getRoomName());
                            return null;
                        }

                        //写入收款数据
                        orderExtVO.setPaidRentUtilities(orderFeesDOListNodeposit.stream().map(OrderFeesDO::getAmount).reduce(BigDecimal.ZERO,
                                (p, q) -> p.add(q)));
                        orderExtVO.setFeeDetail(RentOrderConvert.INSTANCE.convert2(orderFeesDOListNodeposit));


                        //租金账单 存在退租 或者换房情况下 需判断清算单情况
                        if(OrderTypeEnum.DEFAULT.getCode().equals(m.getOrderType()) && Arrays.asList(ContractStatusEnum.NORMAL_END.getCode(),ContractStatusEnum.ABNORMAL_END.getCode())
                                .contains(contractRoomDO.getContractStatus())){
                            Optional<SettlementDO> optionalSettlementDO =
                                    settlementDOList.stream().filter(st -> st.getContractId().compareTo(contractRoomDO.getId()) == 0).findFirst();
                            List<SettlementDetailDO> collect2 = new ArrayList<>();
                            //存在清算单并且账单周期有涉及
                            // 需处理清算单
                            if(optionalSettlementDO.isPresent()  &&  optionalSettlementDO.get().getEvictionTime().compareTo(m.getStartTime())>= 0
                                    && optionalSettlementDO.get().getEvictionTime().compareTo(m.getEndTime())<= 0 ){
                                log.info("todo{}",contractRoomDO.getRoomName());
                                SettlementDO settlementDO = optionalSettlementDO.get();
                                //清算单费项 排除押金
                                List<SettlementDetailDO> collect1 =
                                        finalSettlementDetailDOS.stream().filter(sdds -> sdds.getSettlementId().compareTo(settlementDO.getId()) == 0
                                                        && !sdds.getFeeName().contains("押金"))
                                                .collect(Collectors.toList());
                                //退租情况下
                                if(Arrays.asList(EvictionTypeEnum.NORMAL_RENTING.getCode(),EvictionTypeEnum.BREACH_RENTING.getCode(),EvictionTypeEnum.CONSULT_RENTING.getCode())
                                        .contains(settlementDO.getEvictionType()) &&
                                        //兼容历史bug
                                        !Arrays.asList("1","2","3","4","5","6").contains(settlementDO.getEvictionReason())
                                ){
                                    //在账期内
                                    //流出情况下额外处理
                                    if("out".equals(settlementDO.getFlowType())){
                                        collect2 = collect1;
                                    }
                                }else {
                                    //换租
                                    //新合同第一期账单费项目
                                    List<OrderFeesDO> numOneFeesByContractIds =
                                            rentOrderMapper.getNumOneFeesByContractId(contractRoomDO.getId());
                                    //排除押金
                                    List<OrderFeesDO> newFees =
                                            numOneFeesByContractIds.stream().filter(sdds -> sdds.getAmount().compareTo(BigDecimal.ZERO) > 0
                                                    && !sdds.getFeeName().contains("押金"))
                                            .collect(Collectors.toList());
                                     collect2 = collect1.stream().filter(oldf -> {
                                        //流入项对比
                                        if ("in".equals(oldf.getFlowType())) {
                                            long count =
                                                    newFees.stream().filter(newf -> newf.getFeeId().equals(oldf.getFeeId()) && newf.getAmount().equals(oldf.getAmount())).count();
                                            if(count > 0){
                                                return false;
                                            }
                                        }
                                        return true;
                                    }).collect(Collectors.toList());

                                }

                            }

                            //无数据不进行处理
                            clearOrderDataProces(optionalSettlementDO,collect2,orderExtVO);
                        }

                    }

                    return orderExtVO;
        }).filter(ObjectUtil::isNotNull).peek(p->{
                    //进行费项合并
                    feeItemConsolidation(p);
                }).collect(Collectors.toList());


        return CommonResult.success(collect);
    }

    //进行费项合并
    private void feeItemConsolidation(RentOrderExtVO orderExtVO){
        Map<Long, List<OrderFeeDetailVO>> maps =
                orderExtVO.getFeeDetail().stream().collect(Collectors.groupingBy(OrderFeeDetailVO::getFeeId));
        List<OrderFeeDetailVO> newFees = new ArrayList<>();
        maps.forEach((k,v)->{
           if(v.size() > 1){
               OrderFeeDetailVO orderFeeDetailVO = v.get(0);
               BigDecimal reduce = v.stream().map(OrderFeeDetailVO::getAmount).reduce(BigDecimal.ZERO,
                       (p, q) -> p.add(q));
               orderFeeDetailVO.setAmount(reduce);
               orderFeeDetailVO.setPaidAmount(reduce);
               newFees.add(orderFeeDetailVO);
           }
            newFees.addAll(v);
        });

    }

    /**
     *
     * @param optionalSettlementDO
     * @param collect2
     * @param orderExtVO
     */
    private void clearOrderDataProces(Optional<SettlementDO> optionalSettlementDO,List<SettlementDetailDO> collect2,RentOrderExtVO orderExtVO){
        if(CollectionUtil.isNotEmpty(collect2)){
            SettlementDO settlementDO = optionalSettlementDO.get();
            List<OrderFeeDetailVO> orderFeeDetailVOList = collect2.stream().map(ovo->{
                OrderFeeDetailVO vo = new OrderFeeDetailVO();
                vo.setFlowType(0);
                //费项流出
                if("out".equals(ovo.getFlowType())){
                    BigDecimal subtract =
                            ovo.getAmount().subtract(ovo.getRefundableAmount());
                    vo.setAmount(subtract);
                    vo.setPaidAmount(subtract);
                }else{
                    vo.setAmount(ovo.getAmount());
                    vo.setPaidAmount(ovo.getAmount());
                }
                vo.setOrderId(orderExtVO.getId());
                vo.setFeeId(ovo.getFeeId());
                vo.setFeeName(ovo.getFeeName());
                vo.setStartTime(ObjectUtil.isNotNull(ovo.getOrderStartDate())?ovo.getOrderStartDate().toLocalDate():settlementDO.getEvictionTime());
                vo.setEndTime(ObjectUtil.isNotNull(ovo.getOrderEndDate())?ovo.getOrderEndDate().toLocalDate():settlementDO.getEvictionTime());
                return vo;

            }).filter(ftz->ftz.getAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            //写入收款数据
            orderExtVO.setPaidRentUtilities(orderFeeDetailVOList.stream().map(OrderFeeDetailVO::getAmount).reduce(BigDecimal.ZERO,
                    (p, q) -> p.add(q)));
            orderExtVO.setFeeDetail(orderFeeDetailVOList);
        }

    }


    @Override
    public CommonResult<List<OrderFeeDetailVO>> getFeeListByOrderIds(List<Long> ids) {
        return CommonResult.success(orderFeesService.getOrderDetailByOrderIds(ids));
    }
}
